﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data;
using System.Data.Common;
using System.Xml.Serialization;
using System.IO;
using medicine.General;

namespace medicine.BaseComponents.Groups
{
    public class PeriodsCustomDataSource : IGroupDataSource
    {
        public DbDataReader GetDataSource()
        {           
            DataTable dt = new DataTable();
            dt.Columns.Add("Name");
            dt.Columns.Add("Value");
            DateTime StudyDate = DateTime.Now;
            if (medicine.DAL.MedicineDBStructure.StudyDate!=null)
                StudyDate = (DateTime)medicine.DAL.MedicineDBStructure.StudyDate; 
            //---------------------------------------------------
            // Add Monthes
            for (int j = 5; j >= 0; j--) 
            {
                for (int i = 1; i <= 12; i++)
                {
                    if (j == 5 && i <= StudyDate.Month)
                        continue;
                    if (j == 0 && i > StudyDate.Month)
                        continue;
                    string MonthName = new DateTime(StudyDate.Year - j, i, 1).ToString("MMM");
                    PeriodClass.AddNewElement(dt, MonthName + "/" + (StudyDate.Year - j).ToString().Substring(2), 1, StudyDate.Year - j, i, 1, StudyDate.Year - j, i, DateTime.DaysInMonth(StudyDate.Year - j, i));
                }
            }
            //---------------------------------------------------
            // Add Quarters
            for (int i = 57; i >= -2; i = i - 3)
            {
                DateTime CurrentDate = StudyDate.AddMonths(-i);
                int QRT = ((CurrentDate.Month -1) / 3) + 1;
                int StartMonth = ((QRT - 1) * 3) + 1;
                int EndMonth = StartMonth + 2;
                string DisplayText = "QTR" + QRT.ToString() + "/" + CurrentDate.Year.ToString().Substring(2);
                PeriodClass.AddNewElement(dt, DisplayText, 3, CurrentDate.Year, StartMonth, 1, CurrentDate.Year, EndMonth, DateTime.DaysInMonth(CurrentDate.Year, EndMonth));
            }
            //---------------------------------------------------
            // Add Years
            for (int i = 6; i >= 1; i--)
            {
                DateTime CurrentDate = StudyDate.AddYears(-i);
                string DisplayText = "Year/" + CurrentDate.Year.ToString().Substring(2);
                PeriodClass.AddNewElement(dt, DisplayText, 12, CurrentDate.Year, 1, 1, CurrentDate.Year, 12, DateTime.DaysInMonth(CurrentDate.Year, 12));
            }
            //---------------------------------------------------
            // Add YTD
            for (int i = 4; i >=0; i--)
            {
                string DisplayText = "YTD" + (i + 1);
                //DateTime StartDate = StudyDate.AddMonths((-12 * i) - 1);
                //DateTime EndDate = StartDate.AddMonths(11);
                DateTime StartDate = new DateTime(StudyDate.Year - i, 1, 1);
                DateTime EndDate = new DateTime(StartDate.Year , StudyDate.Month, DateTime.DaysInMonth(StartDate.Year, StudyDate.Month));

                PeriodClass.AddNewElement(dt, DisplayText, 12, StartDate, EndDate);
            }
            //---------------------------------------------------
            // Add MAT
            DateTime StartDateMAT = StudyDate.AddMonths(-12 * 6);
            for (int i = 5; i >= 1; i--)
            {
                StartDateMAT= StartDateMAT.AddMonths(+12);
               //DateTime EndDate = new DateTime(StartDateMAT.AddMonths(12).Year, StartDateMAT.AddMonths(12).Month, DateTime.DaysInMonth(StartDateMAT.AddMonths(12).Year, StartDateMAT.AddMonths(12).Month));
                DateTime EndDate = StartDateMAT.AddMonths(+12);
                string DisplayText = "MAT" + i;
                PeriodClass.AddNewElement(dt, DisplayText, 12, StartDateMAT, EndDate);
            }

            //---------------------------------------------------
            // Add Months
            for (int i = 60; i >= 1; i--)
            {
                DateTime CurrentDate = StudyDate.AddMonths(-i+1);
                string DisplayText = "Month" + i;

                PeriodClass.AddNewElement(dt, DisplayText, 1, CurrentDate.Year, CurrentDate.Month, 1, CurrentDate.Year, CurrentDate.Month, DateTime.DaysInMonth(CurrentDate.Year, CurrentDate.Month));
            }
            //---------------------------------------------------
            // Add Quarters
            int k = 20;
            //for (int i = 60; i >= 1; i = i - 3)
            for (int i = 57; i >= -2; i = i - 3)
            {
            
                DateTime CurrentDate = StudyDate.AddMonths(-i);
                int QRT = ((CurrentDate.Month - 1) / 3) + 1;
                int StartMonth = ((QRT - 1) * 3) + 1;
                int EndMonth = StartMonth + 2;
                string DisplayText = "QTR" + k;
                k--;
                PeriodClass.AddNewElement(dt, DisplayText, 3, CurrentDate.Year, StartMonth, 1, CurrentDate.Year, EndMonth, DateTime.DaysInMonth(CurrentDate.Year, EndMonth));
            }
            //---------------------------------------------------
            // Add 6 months
            System.Collections.Stack StartDateStack = new System.Collections.Stack();
            System.Collections.Stack EndDateStack = new System.Collections.Stack();

            int PeriodLength=6;
            int CurrentPart = GetPeriodPart(StudyDate.Month,PeriodLength); 
            DateTime CurrentDateX= GetPeriodStartDatePlusPeriod( StudyDate, GetPeriodStartMonth(CurrentPart,PeriodLength), PeriodLength);
            for (int i = 10; i >= 1; i = i - 1)
            {
                CurrentDateX = CurrentDateX.AddMonths(-PeriodLength);
                DateTime EndDate = GetPeriodEndDate(CurrentDateX, PeriodLength);
                StartDateStack.Push(CurrentDateX);
                EndDateStack.Push(EndDate);

            }

            for (int i = 10; i >= 1; i = i - 1)
            {
                CurrentDateX = (DateTime)StartDateStack.Pop();
                DateTime EndDate = (DateTime)EndDateStack.Pop();

                string DisplayText = "6Month" + i;
                PeriodClass.AddNewElement(dt, DisplayText, PeriodLength, CurrentDateX, EndDate);
            }
            //k = 10;
            //for (int i = 60; i >= 1; i = i - 6)
            //{
            //    DateTime CurrentDate = StudyDate.AddMonths(-i);
            //    int QRT = (CurrentDate.Month / 6) + 1;
            //    int StartMonth = ((QRT - 1) * 6) + 1;
            //    int EndMonth = StartMonth + 5;
            //    string DisplayText = "6Month" + k;
            //    k--;
            //    PeriodClass.AddNewElement(dt, DisplayText, 6, CurrentDate.Year, StartMonth, 1, CurrentDate.Year, EndMonth, DateTime.DaysInMonth(CurrentDate.Year, EndMonth));
            //}
            //---------------------------------------------------
            return dt.CreateDataReader();
        }

        private int GetPeriodPart(int StudyMonth, int PeriodLength)
        {
            int CurrentPart = (StudyMonth / PeriodLength);
            if (StudyMonth % PeriodLength != 0)
                CurrentPart++;

            return CurrentPart;
        }
        private int GetPeriodStartMonth(int PeriodPart, int PeriodLength)
        {
            return ((PeriodPart - 1) * PeriodLength) + 1;           
        }
        private DateTime GetPeriodStartDatePlusPeriod(DateTime StudyDate, int StartMonth, int PeriodLength)
        {
            return new DateTime(StudyDate.Year, StartMonth, 1).AddMonths(PeriodLength);            
        }
        private DateTime GetPeriodEndDate(DateTime StartDate, int PeriodLength)
        {
            return  new DateTime(StartDate.AddMonths(PeriodLength - 1).Year, StartDate.AddMonths(PeriodLength - 1).Month, DateTime.DaysInMonth(StartDate.AddMonths(PeriodLength - 1).Year, StartDate.AddMonths(PeriodLength - 1).Month));
        }


    }
    [Serializable]
    public class PeriodClass 
    {
        
        public DateTime FromDate;
        public DateTime ToDate;
        public int PeriodLength;
        public string Display = "";

        public PeriodClass()
        {
        }
        public PeriodClass(string Display,int Length,DateTime FromDate,DateTime ToDate)
        {
            this.FromDate = FromDate;
            this.ToDate = ToDate;
            this.PeriodLength = Length;
            this.Display = Display;
        }

        public static void AddNewElement(DataTable dt, string display, int Length, DateTime StartDate,DateTime EndDate)
        {
            AddNewElement(dt, display, Length, StartDate.Year, StartDate.Month, StartDate.Day, EndDate.Year, EndDate.Month, EndDate.Day);
        }

        public static void AddNewElement(DataTable dt,string display,int Length,int StartYear,int StartMonth,int StartDay,int EndYear,int EndMonth,int EndDay)
        {            
            
            DataRow dr=dt.NewRow();
            dr["Name"] = display;
            PeriodClass x = new PeriodClass(display,Length, new DateTime(StartYear, StartMonth, StartDay), new DateTime(EndYear, EndMonth, EndDay));
            dr["Value"] = x.Serialize();
            
            dt.Rows.Add(dr);
        }

        public string Serialize()
        {
            return SerializingUtility.SerializeObjectToXMLString<PeriodClass>(this);
            //StringWriter SW = new StringWriter();
            //XmlSerializer XS = new XmlSerializer(typeof(PeriodClass));
            //XS.Serialize(SW, this);
            //return SW.ToString();
        }

        public static PeriodClass DeSerialize(string XML)
        {
            return SerializingUtility.DeserializeObjectFromXMLString<PeriodClass>(XML);
            //StringReader SR=new StringReader(XML);
            
            //XmlSerializer XS = new XmlSerializer(typeof(PeriodClass));
            //return (PeriodClass)XS.Deserialize(SR);
        }       

    }
}
